import Axios, {
    type AxiosInstance,
    type AxiosError,
    type AxiosResponse,
    type AxiosRequestConfig
} from 'axios';
import store from '@/utils/store';
import { ContentTypeEnum, ResultEnum } from '@/enums/requestEnum';
// import NProgress from '../progress';
import { showFailToast, showLoadingToast, closeToast } from 'vant';
import 'vant/es/toast/style';
import { formatDate, uuid } from '@/utils';

// 默认 axios 实例请求配置
const configDefault = {
    headers: {
        'Content-Type': ContentTypeEnum.FORM_URLENCODED
    },
    timeout: 30000,
    method: 'post',
    baseURL: import.meta.env.VITE_BASE_API,
    data: {}
};

class Http {
    // 当前实例
    private static axiosInstance: AxiosInstance;
    // 请求配置
    private static axiosConfigDefault: AxiosRequestConfig;

    // 请求拦截
    private httpInterceptorsRequest(): void {
        Http.axiosInstance.interceptors.request.use(
            (config: any) => {
                if (config.isLogger) {
                    config.baseURL = import.meta.env.VITE_LOGGER_API;
                }
                return config;
            },
            (error: AxiosError) => {
                showFailToast(error.message);
                return Promise.reject(error);
            }
        );
    }

    // 响应拦截
    private httpInterceptorsResponse(): void {
        Http.axiosInstance.interceptors.response.use(
            (response: AxiosResponse) => {
                // NProgress.done();
                const { config } = response;
                if (config.hasErr) {
                    return response.data;
                }

                const { code, message, data } = response.data;
                // 判断请求是否成功
                const isSuccess = Reflect.has(response.data, 'code') && code === ResultEnum.SUCCESS;
                if (isSuccess) {
                    return data;
                } else {
                    // 处理请求错误
                    showFailToast(message);
                    return Promise.reject(response.data);
                }
            },
            (error: AxiosError) => {
                // NProgress.done();
                // 处理 HTTP 网络错误
                let message = '';
                // HTTP 状态码
                const status = error.response?.status;
                switch (status) {
                    case 400:
                        message = '请求错误';
                        break;
                    case 401:
                        message = '未授权，请登录';
                        break;
                    case 403:
                        message = '拒绝访问';
                        break;
                    case 404:
                        message = `请求地址出错: ${error.response?.config?.url}`;
                        break;
                    case 408:
                        message = '请求超时';
                        break;
                    case 500:
                        message = '服务器内部错误';
                        break;
                    case 501:
                        message = '服务未实现';
                        break;
                    case 502:
                        message = '网关错误';
                        break;
                    case 503:
                        message = '服务不可用';
                        break;
                    case 504:
                        message = '网关超时';
                        break;
                    case 505:
                        message = 'HTTP版本不受支持';
                        break;
                    default:
                        message = '网络连接故障';
                }

                showFailToast(message);
                return Promise.reject(error);
            }
        );
    }

    constructor(config: AxiosRequestConfig) {
        Http.axiosConfigDefault = config;
        Http.axiosInstance = Axios.create(config);
        this.httpInterceptorsRequest();
        this.httpInterceptorsResponse();
    }

    // 通用请求函数
    public request<T>(paramConfig: AxiosRequestConfig, optsConfig: any = {}): Promise<T> {
        const config = { ...Http.axiosConfigDefault, ...paramConfig };
        optsConfig.isLoading &&
            showLoadingToast({
                message: optsConfig.isLoadingText || '加载中...',
                forbidClick: true
            });
        optsConfig = this.setOpts(optsConfig);
        const headers = this.setHeaders(optsConfig);
        if (config.method === 'post') {
            config.data = config.params;
            config.params = {};
        }
        return new Promise((resolve, reject) => {
            Http.axiosInstance
                .request({ ...config, ...optsConfig, headers: { ...config.headers, ...headers } })
                .then((response: any) => {
                    optsConfig.isLoading && closeToast();
                    resolve(response);
                })
                .catch((error) => {
                    optsConfig.isLoading && closeToast();
                    reject(error);
                });
        });
    }

    /**
     * 设置头部信息
     * @returns
     */
    private setHeaders(opts: AxiosRequestConfig = {}) {
        // 处理公共报文
        const { token, deviceId } = store.get('USERINFO') || {};
        const appId = store.get('APP_ID');
        return {
            'bc-pageId': opts.pageId || store.get('PAGE_ID') || '',
            'bc-requestId': opts.requestId || '',
            'boc-version': import.meta.env.VITE_VERSION,
            'boc-deviceId': deviceId || '',
            'boc-platform': 'WE_CHAT_H5',
            'boc-appId': appId || '',
            token: token ? token : '',
            'content-type':
                opts.method === 'GET' ? 'application/x-www-form-urlencoded' : 'application/json'
        };
    }

    private setOpts(opts: any = {}) {
        const requestId = `REQ-${formatDate(new Date(), '{y}{m}{d}')}-${uuid(5, 5)}`;
        return {
            ...opts,
            requestId: opts.requestId || requestId,
            hasErr: opts.hasErr || false
        };
    }
}

export const http = new Http(configDefault);
